/**
 * @File   : EditTable.js
 * @Author : xue.xiaoBing
 * @Date   : 2020/12/19
 * @Desc   : 可编辑表格组件
 **/

import {PlusOutlined} from "@ant-design/icons";
import {Table, Input, Button, Form} from "antd";
import React, {Component, useContext, useState, useEffect, useRef} from "react";


const EditableContext = React.createContext();

const EditableRow = ({index, ...props}) => {
  const [form] = Form.useForm();
  return (
    <Form form={form} component={false}>
      <EditableContext.Provider value={form}>
        <tr {...props} />
      </EditableContext.Provider>
    </Form>
  );
};

const EditableCell = (
  {
    title,
    editable,
    children,
    dataIndex,
    record,
    handleSave,
    ...restProps
  }) => {
  const [editing, setEditing] = useState(false);
  const inputRef = useRef();
  const form = useContext(EditableContext);
  useEffect(() => {
    if (editing) {
      inputRef.current.focus();
    }
  }, [editing]);

  const toggleEdit = () => {
    setEditing(!editing);
    form.setFieldsValue({
      [dataIndex]: record[dataIndex],
    });
  };

  const save = async (e) => {
    try {
      const values = await form.validateFields();
      toggleEdit();
      handleSave({...record, ...values});
    } catch (errInfo) {
      console.log('Save failed:', errInfo);
    }
  };

  let childNode = children;

  if (editable) {
    childNode = editing ? (
      <Form.Item
        style={{
          margin: 0,
        }}
        name={dataIndex}
        rules={[
          {
            required: true,
            message: `${title} is required.`,
          },
        ]}
      >
        <Input ref={inputRef} onPressEnter={save} onBlur={save}/>
      </Form.Item>
    ) : (
      <div
        className="editable-cell-value-wrap"
        style={{
          paddingRight: 24,
        }}
        onClick={toggleEdit}
      >
        {children}
      </div>
    );
  }
  return <td {...restProps}>{childNode}</td>;
};


class EditTable extends Component {
  constructor(props) {
    super(props);
    this.state = {
      dataSource: this.props.dataSource,
      columns: this.props.columns,
    }
  }

  handleAdd = () => {
    this.props.addItem()
  };

  handleSave = (row) => {
    this.props.saveItem(row)
  };

  componentWillReceiveProps(nextProps) {
    this.setState({dataSource: nextProps.dataSource});
  }

  render() {
    const components = {
      body: {
        row: EditableRow,
        cell: EditableCell,
      },
    };
    const columns = this.state.columns.map((col) => {
      if (!col.editable) {
        return col;
      }

      return {
        ...col,
        onCell: (record) => ({
          record,
          editable: col.editable,
          dataIndex: col.dataIndex,
          title: col.title,
          handleSave: this.handleSave,
        }),
      };
    });

    return (
      <div style={{width: '100%'}}>
        {
          this.props.noAdd ? null : (<Button
            onClick={this.handleAdd}
            type="primary"
            style={{
              marginBottom: 16,
            }}>
            <PlusOutlined/> 新增条目
          </Button>)
        }

        <Table
          components={components}
          rowClassName={() => 'editable-row'}
          bordered={this.props.hasBorder !== false}
          dataSource={this.state.dataSource}
          columns={columns}
          expandable={this.props.isExpandable === true ? {
            expandedRowRender: record => (
              this.props.expandableComponent
            ),
            rowExpandable: record => this.props.isExpandable === true,
          } : null}
        />
      </div>
    )
  }
}

export default EditTable